🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / takserver / src / commonTest / kotlin / org / meshtastic / core / takserver / CotDeliveryDedupTest.kt
Displaying Raw • Download
core/takserver/src/commonTest/kotlin/org/meshtastic/core/takserver/CotDeliveryDedupTest.kt 65a1f5ce4d0e4b8eafcd0bbfccafd41dc6ee888a (65a1f5ce) Text, 3.06 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.takserver
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertFalse
Tff7b72import T7ee787kotlin.test.assertTrue
Tff7b72import T7ee787kotlin.time.Duration.Companion.minutes
Tff7b72import T7ee787kotlin.time.Duration.Companion.seconds
Tff7b72import T7ee787kotlin.time.Instant
Tff7b72class T56d364CotDeliveryDedupTest Tb4b4b4{
Tff7b72private Tff7b72var Te6edf3clock Tff7b72= Te6edf3InstantTb4b4b4.Te6edf3fromEpochSecondsTb4b4b4(T79c0ff1Te6edf3_000_000Tb4b4b4)
Tf0883e@Test
Tff7b72fun Td2a8ff`first sighting admitted then immediate exact repeat dropped`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3dedup Tff7b72= Te6edf3CotDeliveryDedupTb4b4b4(Te6edf3ttl Tff7b72= T79c0ff2.Te6edf3minutesTb4b4b4, Te6edf3now Tff7b72= Tb4b4b4{ Te6edf3clock Tb4b4b4}Tb4b4b4)
Tff7b72val Te6edf3xml Tff7b72= Ta5d6ff"""Ta5d6ff<event uid=Ta5d6ff"Ta5d6ffTAKTALK-MESSAGE-abcTa5d6ff"Ta5d6ff type=Ta5d6ff"Ta5d6ffm-t-tTa5d6ff"Ta5d6ff><detail><text>hi</text></detail></event>Ta5d6ff"""
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Te6edf3xmlTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6fffirst copy deliveredTa5d6ff"Tb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Te6edf3xmlTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffidentical copy within TTL droppedTa5d6ff"Tb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Te6edf3xmlTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffand againTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`distinct events are all admitted`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3dedup Tff7b72= Te6edf3CotDeliveryDedupTb4b4b4(Te6edf3now Tff7b72= Tb4b4b4{ Te6edf3clock Tb4b4b4}Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"""Ta5d6ff<event uid=Ta5d6ff"Ta5d6ffATa5d6ff"Ta5d6ff/>Ta5d6ff"""Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"""Ta5d6ff<event uid=Ta5d6ff"Ta5d6ffBTa5d6ff"Ta5d6ff/>Ta5d6ff"""Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`same uid but changed content is not a duplicate`Tb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// PLIs reuse the device uid every position update — keying on exact XML lets updates through.
Tff7b72val Te6edf3dedup Tff7b72= Te6edf3CotDeliveryDedupTb4b4b4(Te6edf3now Tff7b72= Tb4b4b4{ Te6edf3clock Tb4b4b4}Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"""Ta5d6ff<event uid=Ta5d6ff"Ta5d6ffNTa5d6ff"Ta5d6ff type=Ta5d6ff"Ta5d6ffa-f-G-U-CTa5d6ff"Ta5d6ff><point lat=Ta5d6ff"Ta5d6ff1.0Ta5d6ff"Ta5d6ff/></event>Ta5d6ff"""Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"""Ta5d6ff<event uid=Ta5d6ff"Ta5d6ffNTa5d6ff"Ta5d6ff type=Ta5d6ff"Ta5d6ffa-f-G-U-CTa5d6ff"Ta5d6ff><point lat=Ta5d6ff"Ta5d6ff2.0Ta5d6ff"Ta5d6ff/></event>Ta5d6ff"""Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`duplicate is re-admitted once the TTL window elapses`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3dedup Tff7b72= Te6edf3CotDeliveryDedupTb4b4b4(Te6edf3ttl Tff7b72= T79c0ff2.Te6edf3minutesTb4b4b4, Te6edf3now Tff7b72= Tb4b4b4{ Te6edf3clock Tb4b4b4}Tb4b4b4)
Tff7b72val Te6edf3xml Tff7b72= Ta5d6ff"""Ta5d6ff<event uid=Ta5d6ff"Ta5d6ffXTa5d6ff"Ta5d6ff/>Ta5d6ff"""
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Te6edf3xmlTb4b4b4)Tb4b4b4)
Te6edf3clock Tff7b72+Tff7b72= T79c0ff6T79c0ff0.Te6edf3seconds
Te6edf3assertFalseTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Te6edf3xmlTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffstill within the 2-minute windowTa5d6ff"Tb4b4b4)
Te6edf3clock Tff7b72+Tff7b72= T79c0ff9T79c0ff0.Te6edf3seconds T8b949e// 150s since first sighting > 120s TTL
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Te6edf3xmlTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffwindow expired, delivered againTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tff7b72fun Td2a8ff`cache is bounded by maxEntries and evicts oldest`Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3dedup Tff7b72= Te6edf3CotDeliveryDedupTb4b4b4(Te6edf3ttl Tff7b72= T79c0ff6T79c0ff0.Te6edf3minutesTb4b4b4, Te6edf3maxEntries Tff7b72= T79c0ff2Tb4b4b4, Te6edf3now Tff7b72= Tb4b4b4{ Te6edf3clock Tb4b4b4}Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"Ta5d6ffbTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"Ta5d6ffcTa5d6ff"Tb4b4b4)Tb4b4b4) T8b949e// evicts oldest ("a")
Te6edf3assertTrueTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffoldest was evicted, so treated as newTa5d6ff"Tb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3dedupTb4b4b4.Te6edf3admitTb4b4b4(Ta5d6ff"Ta5d6ffcTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffstill cachedTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.05s